#pragma once
#include<functional>
#include"Socket.hpp"
#include<iostream>
#include<signal.h>
 
using namespace std;
 
using func_t =function<string (string& package)>;

class TcpServer
{
public:
    TcpServer(uint16_t port,func_t calback):_port(port),_calback(calback)
    {}
    bool Init()
    {
        _listen_sockfd.Socket();  
        cout<<"create socket successfully...listen_sockfd:"<<_listen_sockfd._sockfd<<endl;
        _listen_sockfd.Bind(_port);
        cout<<"bind socket successfully...listen_sockfd:"<<_listen_sockfd._sockfd<<endl;
        _listen_sockfd.Listen();
        cout<<"listen socket successfully...listen_sockfd:"<<_listen_sockfd._sockfd<<endl;
        return true;
    }
    void Start()
    {
        signal(SIGCHLD,SIG_IGN);
        signal(SIGPIPE,SIG_IGN);
        while(true)
        {   
            string client_ip;
            uint16_t client_port;
            int sockfd=_listen_sockfd.Accept(client_ip,client_port);//接收到的sockfd是给上层用户使用的文件描述符
            if(sockfd<0)
                continue;

            cout<<"receive a new link,sockfd:"<<sockfd<<"client_ip:"<<client_ip<<",client_port:"<<client_port<<endl;
            if(fork()==0)
            {
                //子进程提供服务
                _listen_sockfd.Close();
                //数据计算
                string inbuffer_stream;//用户级缓冲区，存放那些不完整的报文
                while(true)
                {
                    char buffer[128];
                    ssize_t n=read(sockfd,buffer,sizeof(buffer)-1);//将接收缓冲区内的数据拷贝到buffer内，一次拷贝127字节大小的数据，留个空位放'\0'
                    if(n>0)
                    {
                        buffer[n]='\0';
                        inbuffer_stream+=buffer;//处于未解封、序列化状态

                        cout<<"client send str,len:"<<inbuffer_stream.c_str()<<endl;

                        string info=_calback(inbuffer_stream);//判断收到的报文是否完整，若完整，就处理，处理结果给info;不完整，就继续读
                        if(info.empty()) continue;
 
                        write(sockfd,info.c_str(),info.size());//将计算结果写入发送缓冲区
                    }
                    else break;
                }

                exit(0);
            }

            close(sockfd);
        }
    }
    ~TcpServer()
    {}
private:
    Sock _listen_sockfd;//封装后的_sockfd
    uint16_t _port;
    func_t _calback;
};